/***************************************************************************************************
  *Copyright(C),2017-2020,Sumscope
  *FileName	:  QuoteBoardLoadCTDInfo
  *Author	:  Givins.zhu
  *Version	:  2.0
  *Date		:  2019/10/15
  *Desc		:  获取国债期货活跃券做多基差排行榜对应的债券信息
  *History	:
  *Email    :  Givins.zhu@sumscope.com
***************************************************************************************************/
#pragma once
#include <map>
#include <list>
#include <set>
#include <QObject>
#include <qbprotocol/include/SSQBModel.h>
#include "NatDebtFutureToolsParam.h"
#include <qbmessage/include/message_bond.h>
#include <qbtools/message/MessagePoster.h>
#include <core/Events.h>
#include <core/strings/string_util.h>

//SS_QUOTE_BOARD_LOAD_CTD //做多基差
#define LOAD_CTD_DOUBLE_VALID -999

class S_TFBONDLIB_EXPORT CCTDGetInfo{
public:
	CCTDGetInfo(){
		clear();
	}
	
	void clear(){
		initialPrice();
		m_strTFID = m_strBondKey = "";
		m_strBondCode = m_strDuration = "";
		m_nBroker = -1;
		m_nDelivdate = 0;
		m_fFactor = 0;
		m_dbBP = 0.0f;
	}

	void initialPrice(){
		m_dbTFYeild = m_dbTFPreYeild = m_dbIRR = m_dbBasicPrc = LOAD_CTD_DOUBLE_VALID;
	}

	CCTDGetInfo& operator = (const CCTDGetInfo& obj){
		m_strBondKey = obj.m_strBondKey;
		m_strTFID = obj.m_strTFID;
		m_nBroker = obj.m_nBroker;
		m_dbIRR = obj.m_dbIRR;
		m_dbBasicPrc = obj.m_dbBasicPrc;
		m_nDelivdate = obj.m_nDelivdate;
		m_dbTFYeild = obj.m_dbTFYeild;
		m_dbTFPreYeild = obj.m_dbTFPreYeild;
		m_fFactor = obj.m_fFactor;
		m_strDuration = obj.m_strDuration;
		m_dbBP = obj.m_dbBP;
		m_strBondCode = obj.m_strBondCode;
		return *this;
	}

	std::string m_strBondKey;
	std::string m_strTFID;
	int m_nBroker;
	int m_nDelivdate;
	double m_dbIRR;
	double m_dbBasicPrc;
	std::string m_strDuration;  //现券久期,仅作参数使用,外部计算
	std::string m_strBondCode;  //BondCode,仅作参数使用,外部计算
	double m_dbBP;			//收益率BP差,供参数使用,外部计算
	double m_dbTFYeild;
	double m_dbTFPreYeild; //国债期货价格对应的利率
	float m_fFactor;
};

class S_TFBONDLIB_EXPORT CQuoteBoardSingleCTDInfo{
public:
	CQuoteBoardSingleCTDInfo(const std::string& strTFID = ""){ clear(strTFID); }
	~CQuoteBoardSingleCTDInfo(){}

	void clear(const std::string& strTFID = ""){
		if (!strTFID.empty())m_strTFID = strTFID;
		m_strTFKey = "";
		m_deliveryDate = 0;
		m_fTFYesPrice = m_fTFPrice = 0.0f;
		m_setBondFactor.clear();
	}

	bool setFactor(xConvertFactorsAck_c* ack){
		if (!ack) return false;
		std::list<xConvertFactorsUnit_c>::const_iterator itr = ack->m_List.begin();
		bool bCur = false;
		std::string stKey;
		int nDel;
		for (; itr != ack->m_List.end(); itr++){
			nDel = atoi(itr->m_deliverDate);
			if (nDel != m_deliveryDate) continue;
			stKey = qb::base::string_format("%s", itr->m_bondKey);
			std::map<std::string, float>::iterator itKey = m_setBondFactor.begin();
			for (; itKey != m_setBondFactor.end(); itKey++){
				if (itKey->first.find(stKey) != std::string::npos){
					bCur = true;
					itKey->second = itr->m_convertFactors;
				}
			}
		}
		return bCur;
	}

	bool setTFRefBond(xQBRefBondList_c* pList){
		if (!pList) return false;
		std::list<xQBRefBond_c>::const_iterator itr = pList->m_List.begin();
		if (itr == pList->m_List.end() || strcmp(m_strTFKey.c_str(), itr->m_TF_Key) != 0) return false;
		std::string strFacKey;
		for (; itr != pList->m_List.end(); itr++){
			strFacKey = qb::base::string_format("%s.CIB", itr->m_Bond_Key);
			m_setBondFactor[strFacKey] = itr->m_Conversion_Factor;
		}
		return true;
	}

	std::string m_strTFID;
	std::string m_strTFKey;
	int m_deliveryDate;
	float m_fTFPrice;
	float m_fTFYesPrice;//昨结
	std::map<std::string, float> m_setBondFactor;//转化因子
};

class S_TFBONDLIB_EXPORT CQuoteBoardLoadCTDInfo
	: public QObject,
	  public MessageReceiver,
	  public CUnknownObject<INetworkEventObserver> {
	Q_OBJECT
public:
 	CQuoteBoardLoadCTDInfo();
 	~CQuoteBoardLoadCTDInfo();
 
public:
// 	void cancelRegisterPrice(HWND hWnd);
 	void loadCTDInfo(CCTDGetInfo& ctdinfo, bool needRate=false/*是否需要期货利率相关*/);
 	void clear();

protected:
	void onDataArrived(const qb::SSAckMsg& msg) override;
	STDMETHOD_(void, OnForceQuit) (THIS_ int32_t connect_id) override {}
	STDMETHOD_(void, OnDisConnect) (THIS_ int32_t connect_id) override {}
	STDMETHOD_(void, OnRecover) (THIS_ int32_t connect_id) override;

protected slots:
	void onDataResponse(int funcId);
	void onRecvSignal(const xMarketSignalInfo_t* signal);

signals:
	void ctdChanged();

private:
	unsigned int getPreWorkDay(unsigned int date);
	bool isActive() const { return m_CTDActive; }
 	void rebuildData();
 	void initialTFData();
 	void initialBroker();
 	void dealRecvBond(xNatDebtActiveBondAck_c* ack);
 	void reqTFRefBond();
 	bool checkData(bool mstReget = false);
 	void reqActiveBond();
 	void reqTFPrice(const std::set<std::string>& TFs);
 	void reGetAllTFData();
 	void notifyChange();
 	void loadCurrentTF(std::set<std::string>& TFs);
 	void getCombKey(const std::string& tfId, const std::string& bondkey, int brk, std::string& comb);
 	void unregisterCurrentXBond();
 	void activeCTD();
 	void stopActiveCTD();

 	void caculateAll();
 	void calculateTF(std::string TF = "");
 	void calculateBondkey(const std::string& bond);
 	void calcuFromPrice(CNatDebtCalParam& param, int delDate, double& dbTFYtm);
 	void calculateSingle(CCTDGetInfo& ctdinfo);

private:
	qb::base::CSLock m_lock;
	std::set<int> m_setBroker;
	std::map<std::string, CCTDGetInfo> m_mapTFBondPrice; //合约+现券数据 tfid+bondkey+broker->CCTDGetInfo
	std::map<std::string, CQuoteBoardSingleCTDInfo> m_mapTFInfo; //合约相关的信息 tfid->CQuoteBoardSingleCTDInfo
	std::map<std::string, TW_BOND> m_mapReqBond;
	std::set<std::string> m_currentKey;
	std::set<std::string> m_setFundamentalBond;//已经请求过的券
	int m_validDate;
	bool m_CTDActive;  //是否正在使用
	xNatDebtActiveBondAck_c m_activeBond;
	eventpp::internal_::EventDispatcherBase<std::string, void(const qb::SSAckMsg*), eventpp::DefaultPolicies, void>::Handle m_handler;
 };
 
S_TFBONDLIB_EXPORT CQuoteBoardLoadCTDInfo& getCTDInfo();
